package cc.iotkit.manager.service.impl;

import cc.iotkit.common.api.PageRequest;
import cc.iotkit.common.api.Paging;
import cc.iotkit.common.utils.MapstructUtils;
import cc.iotkit.common.utils.StringUtils;
import cc.iotkit.data.record.IDoorAccessRecordData;
import cc.iotkit.manager.dto.bo.report.DoorAccessRecordBo;
import cc.iotkit.manager.dto.vo.record.DoorAccessRecordVo;
import cc.iotkit.manager.dto.vo.record.DoorAccessStaticVo;
import cc.iotkit.manager.service.DataOwnerService;
import cc.iotkit.manager.service.DoorAccessRecordService;
import cc.iotkit.model.report.DoorAccessRecord;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Service
public class DoorAccessRecordServiceImpl implements DoorAccessRecordService {

    @Autowired
    private IDoorAccessRecordData doorAccessRecordData;

    @Autowired
    private DataOwnerService dataOwnerService;

    @Override
    public Paging<DoorAccessRecordVo> selectPageDoorAccessRecordList(PageRequest<DoorAccessRecord> query) {
        return MapstructUtils.convert(doorAccessRecordData.findAll(query), DoorAccessRecordVo.class);
    }

    @Override
    public List<DoorAccessRecordVo> selectDoorAccessRecordList(DoorAccessRecord recordBo) {
        List<DoorAccessRecord> doorAccessRecord = getDoorAccessRecord(recordBo);
        return MapstructUtils.convert(doorAccessRecord, DoorAccessRecordVo.class);
    }

    private List<DoorAccessRecord> getDoorAccessRecord(DoorAccessRecord recordBo) {
        return doorAccessRecordData.selectDoorAccessRecordList(recordBo);
    }

    @Override
    public Integer save(DoorAccessRecordBo data) {
        DoorAccessRecord role = doorAccessRecordData.save(data.to(DoorAccessRecord.class));

        return 1;
    }

    @Override
    public List<DoorAccessStaticVo> staticCountByHours(String deviceId, Date endTime) {

        Date endDate = DateUtils.ceiling(endTime, Calendar.HOUR);
        Date startDate = DateUtils.addDays(endDate, -1);

        DoorAccessRecord record = new DoorAccessRecord();
//        record.setDateTimeBegin(startDate);
//        record.setDateTimeEnd(endDate);
        record.setDeviceId(StringUtils.isBlank(deviceId) ? null : deviceId);
        List<DoorAccessRecord> records = doorAccessRecordData.selectDoorAccessRecordList(record);

        records.sort(new Comparator<DoorAccessRecord>() {
            @Override
            public int compare(DoorAccessRecord o1, DoorAccessRecord o2) {

                int r = o1.getDateTime().compareTo(o2.getDateTime());
                if (r == 0) {
                    return o1.getId().compareTo(o2.getId());
                }
                return r;

            }
        });
        // 将记录按小时聚合分组
        Map<LocalDateTime, List<DoorAccessRecord>> groupedByHour = records.stream()
                .collect(Collectors.groupingBy(
                        x -> x.getDateTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime().withMinute(0).withSecond(0).withNano(0) // 将时间设置为整点
                ));

        List<DoorAccessStaticVo> staticVos = new ArrayList<>();
        //重新封装结果
        groupedByHour.forEach((key, value) -> {
            System.out.println("Hour: " + key.getHour() + ", Records: " + value.size());
            DoorAccessStaticVo vo = new DoorAccessStaticVo();
            vo.setHours(key.getHour());
            vo.setCount(value.size());
            staticVos.add(vo);
        });

        /**
         * 排序结果
         */
        staticVos.sort(new Comparator<DoorAccessStaticVo>() {
            @Override
            public int compare(DoorAccessStaticVo o1, DoorAccessStaticVo o2) {

                int r = o1.getHours().compareTo(o2.getHours());
                if (r == 0) {
                    return o1.getHours().compareTo(o2.getHours());
                }
                return r;

            }
        });
        return staticVos;
    }
}
